package com.zealcomm.ivcscustomer.service

import android.annotation.SuppressLint
import android.content.*
import android.media.projection.MediaProjectionManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.IBinder
import android.text.TextUtils
import android.view.KeyEvent
import android.webkit.JavascriptInterface
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.Fragment
import com.google.zxing.BarcodeFormat
import com.yanzhenjie.permission.AndPermission
import com.yanzhenjie.permission.runtime.Permission
import com.zco.base.BaseManager
import com.zco.base.ServerCallback
import com.zco.base.annotations.CommandStatus
import com.zco.base.annotations.LinkType
import com.zco.base.annotations.StreamType
import com.zco.base.entity.*
import com.zco.ccs.CcsMessage
import com.zco.ccs.annotations.InvitationProgressType
import com.zco.ccs.annotations.ScanCodeType
import com.zco.ccs.entity.*
import com.zco.ivcs.customer.IvcsCustomerCallback
import com.zco.ivcs.customer.IvcsCustomerEvent
import com.zco.ivcs.customer.base.entity.*
import com.zco.util.*
import com.zco.util.widget.MyProgressDialog
import com.zealcomm.annotations.ChatMessageType
import com.zealcomm.annotations.ChatRoleType
import com.zealcomm.annotations.SystemTraceType
import com.zealcomm.commonui.base.BaseCallback
import com.zealcomm.commonui.base.BaseFragment
import com.zealcomm.commonui.base.BaseFragmentActivity
import com.zealcomm.commonui.beans.MapLocationBean
import com.zealcomm.commonui.beans.MessageContent
import com.zealcomm.commonui.beans.SystemTraceBean
import com.zealcomm.ivcscustomer.R
import com.zealcomm.ivcscustomer.app.IvcsApplication
import com.zealcomm.ivcscustomer.chatroom.ChatRoomFragment
import com.zealcomm.ivcscustomer.databinding.DialogCollectCustomerInfoBinding
import com.zealcomm.ivcscustomer.fragment.MakeChoiceFragment
import com.zealcomm.ivcscustomer.fragment.MessageSummaryFragment
import com.zealcomm.ivcscustomer.fragment.ScanFragment
import com.zealcomm.ivcscustomer.fragment.SummaryConfirmFragment
import com.zealcomm.ivcscustomer.pdfview.PdfviewFragment
import com.zealcomm.ivcscustomer.service.TipsService.TipsBinder
import com.zealcomm.ivcscustomer.signature.SignatureFragment
import com.zealcomm.ivcscustomer.utils.ChatMessageUtil
import com.zealcomm.ivcscustomer.utils.SoftHideKeyBoardUtil
import com.zealcomm.ivcscustomer.utils.StatusBarUtils
import com.zealcomm.ivcscustomer.webview.MyJavascriptInterface
import com.zealcomm.ivcscustomer.webview.WebViewFragment
import com.zealcomm.ivcscustomer.widget.AlertDialogUtil
import com.zealcomm.utils.MapUtil
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.json.JSONException
import org.json.JSONObject
import java.text.SimpleDateFormat
import java.util.*

class MainActivity : BaseFragmentActivity() {

    // 是否是音频呼叫
    var onlyAudio = false
    lateinit var captureScreenService: Intent
    private var serviceTypeChoiceFragment: ServiceTypeChoiceFragment? = null
    private var roomFragment: RoomFragment? = null
    private var customerTypeListFragment: CustomerTypeListFragment? = null
    private var mServiceListFragment: ServiceListFragment? = null
    private var mChatRoomFragment: ChatRoomFragment? = null
    private var videoSettingsFragment: VideoSettingsFragment? = null
    var submitBaseInfoFragment: SubmitBaseInfoFragment? = null
    var idCardAndBankInfo = IDCardAndBankInfo()

    // 只用于区分提示时的语义，不能用作通信状态的判断
    private var isTransfer = false
    private var agentNumber = 0

    private var obtainLocationTimer: Timer? = null
    private var hasGetLocation = false
    private val OBTAIN_LOCATION_TIME_OUT = 20000L
    private var hasShowForm = false
    private var hasSubmitForm = false
    private var scanCodeSessionMessage: SessionMessage<Command<Any>>? = null
    private var requestLocationSessionMessage: SessionMessage<Command<Any>>? = null
    private val joinedUsers = mutableListOf<SessionMessage.OriginUserBean>()

    @JvmField
    var businessScenarioList: ArrayList<BusinessScenariosBean.BusinessScenario> = ArrayList()

    @JvmField
    var messageContents = ArrayList<MessageContent>()

    private val REQUEST_SHARE_CODE = 1002
    private var conn: TipsConn? = null
    private var tipsBinder: TipsBinder? = null
    private var picture: String? = null
    private var fullName: String? = null
    private var gender: String? = null
    private var overlayPermissionUtil: OverlayPermissionUtil? = null

    // 用户信息的 form id
    var formId = -1

    var isRobot = false

    override fun onCreate(savedInstanceState: Bundle?) {
        StatusBarUtils.statusBarTransparent(this)
        StatusBarUtils.setAndroidNativeLightStatusBar(this, true)
        super.onCreate(savedInstanceState)
        picture = intent.getStringExtra("picture")
        fullName = intent.getStringExtra("fullName")
        gender = intent.getStringExtra("gender")
        captureScreenService = Intent(this , CaptureScreenService::class.java)
        serviceTypeChoiceFragment = ServiceTypeChoiceFragment()
        addFragmentNotBackStack(serviceTypeChoiceFragment)
        IvcsApplication.registerEvent(ivcsCustomerEvent)
        SoftHideKeyBoardUtil.assistActivity(this)
        val it = Intent(this, TipsService::class.java)
        conn = TipsConn()
        bindService(it, conn!!, BIND_AUTO_CREATE)
        getBusinessScenario()
    }

    fun showSubmitBaseInfo() {
        submitBaseInfoFragment = SubmitBaseInfoFragment()
        showFragment(submitBaseInfoFragment)
    }

    fun showVideoSettings() {
        videoSettingsFragment = VideoSettingsFragment()
        showFragment(videoSettingsFragment)
    }

    fun showServiceList() {
        mServiceListFragment = ServiceListFragment()
        showFragment(mServiceListFragment)
    }

    fun showCustomerTypeList() {
        customerTypeListFragment = CustomerTypeListFragment.newInstance(businessScenarioList)
        showFragment(customerTypeListFragment)
    }

    fun removeCustomerTypeList(businessScenario: BusinessScenariosBean.BusinessScenario) {
        if (customerTypeListFragment != null) {
            removeFragment()
            customerTypeListFragment = null
            mServiceListFragment?.selectBusinessScenario = businessScenario
        }
    }

    fun removeVideoSettings(videoSettings: Any) {
        if (null != videoSettingsFragment) {
            removeFragment()
            videoSettingsFragment = null
            // TODO 设置视频参数
        }
    }

    fun removeServiceTypeChoice() {
        if (serviceTypeChoiceFragment != null) {
            removeFragment()
            serviceTypeChoiceFragment = null
        }
    }

    fun showChatRoom() {
        mChatRoomFragment = ChatRoomFragment()
        showFragment(mChatRoomFragment)
    }

    fun removeChat() {
        if (mChatRoomFragment != null) {
            removeFragment()
            mChatRoomFragment = null
        }
    }

    fun onScanQRCodeSuccess(scanResult: String?, format: BarcodeFormat?) {
        addChatMessage(
            MessageContent(
                ChatRoleType.CUSTOMER,
                SessionMessage(
                    ChatMessageType.COMMAND, Command(
                        CcsMessage.CCS_SCAN_CODE, "扫码成功，${
                            if (format == BarcodeFormat.QR_CODE) {
                                "二维码"
                            } else {
                                "条形码"
                            }
                        }:$scanResult"
                    )
                )
            )
        )
        roomFragment?.showSmallRenderer(true)
        IvcsApplication.republish()
        if (scanResult == null) {
            ToastUtil.showShort("无法识别")
        } else {
            val messageConfirmBean = MessageConfirmBean<Any>()
            messageConfirmBean.answer = MessageConfirmBean.Reply.OK.value()
            IvcsApplication.sendMessageConfirmation(messageConfirmBean, null)
            FragmentUtil.removeFragmentImmediate(this)
            if (scanResult.startsWith("http", true)) {
                showFragment(
                    WebViewFragment.getInstance(
                        scanResult,
                        null
                    )
                )
            } else {
                AlertDialog.Builder(this).setTitle("扫码成功")
                    .setMessage(scanResult)
                    .setPositiveButton("确定", null)
                    .create().show()
            }
            val systemTraceBean = SystemTraceBean()
            val scanCodeResultBean = ScanCodeResultBean()
            scanCodeResultBean.code = scanResult
            if (format == BarcodeFormat.QR_CODE) {
                systemTraceBean.businessType =
                    SystemTraceType.SCANNER_QRCODE
                systemTraceBean.message = "二维码扫描成功"
                scanCodeResultBean.type = ScanCodeType.QR_CODE
            } else {
                systemTraceBean.businessType =
                    SystemTraceType.SCANNER_QUCODE
                systemTraceBean.message = "扫描条形码成功"
                scanCodeResultBean.type = ScanCodeType.BAR_CODE
            }
            scanCodeSessionMessage!!.data!!.data = scanCodeResultBean
            scanCodeSessionMessage!!.data!!.status = CommandStatus.DONE
            IvcsApplication.ivcsCustomer!!.sendPeerResponse(
                scanCodeSessionMessage!!.from,
                scanCodeSessionMessage!!.data,
                null
            )
            val result = SystemTraceBean.Result()
            result.code = 200
            result.message = scanResult
            systemTraceBean.result = result
            IvcsApplication.sendCustomMessage(
                systemTraceBean,
                object : IvcsCustomerCallback {
                    override fun onSuccess() {
                        val messageConfirmBean =
                            MessageConfirmBean<Any>()
                        messageConfirmBean.answer = "ok"
                        IvcsApplication.sendMessageConfirmation(
                            messageConfirmBean,
                            null
                        )
                    }

                    override fun onFailed(
                        code: Int,
                        error: String?
                    ) {
                    }
                })
        }
    }

    fun onScanCodeCanceled() {
        addChatMessage(
            MessageContent(
                ChatRoleType.CUSTOMER, SessionMessage(
                    ChatMessageType.COMMAND,
                    Command(CcsMessage.CCS_SCAN_CODE, "拒绝扫码")
                )
            )
        )
        this.scanCodeSessionMessage?.data?.status = CommandStatus.REJECTED
        this.scanCodeSessionMessage?.data?.id = this.scanCodeSessionMessage?.data?.cmdId!!
        IvcsApplication.ivcsCustomer!!.sendPeerResponse(
            this.scanCodeSessionMessage?.from,
            this.scanCodeSessionMessage?.data,
            null
        )
        roomFragment?.showSmallRenderer(true)
        IvcsApplication.republish()
    }

    fun showRoom() {
        runOnUiThread {
            roomFragment = RoomFragment()
            showFragment(roomFragment)
        }
    }

    fun removeRoom() {
        if (roomFragment != null) {
            removeFragment()
            roomFragment = null
        }
    }

    public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        overlayPermissionUtil?.onActivityResult(this, requestCode, resultCode, data)
        if (requestCode == REQUEST_SHARE_CODE && data != null) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                captureScreenService.putExtra(CaptureScreenService.CAPTURE_SCREEN_DATA , data)
                startForegroundService(captureScreenService)
            }else{
                IvcsApplication.screenShare(
                    data!!,
                    StreamType.CUSTOMER_SCREEN,
                    object : IvcsCustomerCallback {
                        override fun onSuccess() {}
                        override fun onFailed(code: Int, error: String) {}
                    })
            }
        }
    }

    override fun onDestroy() {
        if (null != obtainLocationTimer) {
            obtainLocationTimer!!.cancel()
            obtainLocationTimer = null
        }
        stopService(captureScreenService)
        super.onDestroy()
    }

    private inner class TipsConn : ServiceConnection {
        override fun onServiceConnected(name: ComponentName, service: IBinder) {
            tipsBinder = service as TipsBinder
        }

        override fun onServiceDisconnected(name: ComponentName) {}
    }

    private var ivcsCustomerEvent = object : IvcsCustomerEvent {

        private fun rejectGetLocation(code: Int, reason: String?, message: String?) {
            val systemTraceBean = SystemTraceBean()
            systemTraceBean.businessType =
                SystemTraceType.GET_CUSTOMER_LOCATION
            systemTraceBean.message = "获取地理位置失败"
            val result = SystemTraceBean.Result()
            result.code = 400
            if (null == message) {
                result.message = systemTraceBean.message
            } else {
                result.message = message
            }
            systemTraceBean.result = result
            IvcsApplication.sendCustomMessage(
                systemTraceBean,
                object : IvcsCustomerCallback {
                    override fun onSuccess() {
                        IvcsApplication.ivcsCustomer!!.confirmRequestLocation(
                            MessageConfirmBean.Reply.REJECT,
                            null
                        )
                        addChatMessage(
                            MessageContent(
                                ChatRoleType.CUSTOMER,
                                SessionMessage(
                                    ChatMessageType.COMMAND,
                                    Command(CcsMessage.CCS_REQUEST_LOCATION, "获取地理位置失败")
                                )
                            )
                        )
                    }

                    override fun onFailed(code: Int, error: String?) {
                    }
                })
            // 发送指令响应消息
            val getLocationResultBean = GetLocationResultBean()
            getLocationResultBean.code = code
            getLocationResultBean.reason = reason
            requestLocationSessionMessage!!.data.data = getLocationResultBean
            requestLocationSessionMessage!!.data.status = CommandStatus.FAILED
            IvcsApplication.ivcsCustomer!!.sendPeerResponse(
                requestLocationSessionMessage!!.from,
                requestLocationSessionMessage!!.data, null
            )
        }

        override fun onScanCode(
            scanCodeSessionMessage: SessionMessage<Command<Any>>,
            scanCode: Boolean
        ) {
            runOnUiThread {
                val scanCodeImMessage = SessionMessage<Command<Any>>(ChatMessageType.COMMAND)
                scanCodeImMessage.fromUser = scanCodeSessionMessage.fromUser
                if (scanCode) {
                    scanCodeImMessage.data = Command(CcsMessage.CCS_SCAN_CODE, "请求扫码")
                    addChatMessage(MessageContent(ChatRoleType.AGENT, scanCodeImMessage))
                    this@MainActivity.scanCodeSessionMessage = scanCodeSessionMessage
                    // 由于扫码操作会重新获得摄像头设备，所以这里先停止本地的推流
                    IvcsApplication.stopLocalStream()
                    roomFragment?.showSmallRenderer(false)
                    showFragment(ScanFragment())
                } else {
                    AlertDialogUtil.dismiss()
                    if ("timeout" == scanCodeSessionMessage.data.reason) {
                        scanCodeImMessage.data = Command(CcsMessage.CCS_SCAN_CODE, "扫码超时")
                        addChatMessage(MessageContent(ChatRoleType.AGENT, scanCodeImMessage))
                        // 不要加提示，原因见：ivcs-1689
                        // ToastUtil.showTopToast("扫码超时")
                    } else {
                        scanCodeImMessage.data = Command(CcsMessage.CCS_SCAN_CODE, "取消扫码")
                        addChatMessage(MessageContent(ChatRoleType.AGENT, scanCodeImMessage))
                        ToastUtil.showTopToast("坐席已取消扫码")
                    }
                    supportFragmentManager.fragments?.let {
                        if (it[it.size - 1] is ScanFragment) {
                            removeFragment()
                        }
                    }
                }
            }
        }

        override fun onSummaryConfirm(summaryConfirmSessionMessage: SessionMessage<Command<CommandConfirmBaseBean<MutableList<SummaryConfirmBean>>>>) {
            runOnUiThread {
                showFragment(SummaryConfirmFragment(summaryConfirmSessionMessage))
            }
        }

        override fun onMessageSummary(messageSummarySessionMessage: SessionMessage<Command<CommandViewBaseBean<MutableList<MessageSummaryBean>>>> , cancel:Boolean) {
            runOnUiThread {
                if (cancel){
                    if (supportFragmentManager.fragments.last() is MessageSummaryFragment){
                        removeFragment()
                    }
                }else{
                    showFragment(MessageSummaryFragment(messageSummarySessionMessage))
                }
            }
        }

        override fun onWaitingRead() {

        }

        override fun onRequestLocation(requestLocationSessionMessage: SessionMessage<Command<Any>>) {
            this@MainActivity.requestLocationSessionMessage = requestLocationSessionMessage
            val requestLocationImMessage = SessionMessage<Command<Any>>(ChatMessageType.COMMAND)
            requestLocationImMessage.fromUser = requestLocationSessionMessage.fromUser
            requestLocationImMessage.data = Command(CcsMessage.CCS_REQUEST_LOCATION, "请求获取地理位置")
            addChatMessage(MessageContent(ChatRoleType.AGENT, requestLocationImMessage))
            hasGetLocation = false
            runOnUiThread {
                AlertDialogUtil.showSimpleDialog(
                    this@MainActivity,
                    "坐席请求获取您的位置信息，是否同意？"
                ) { dialog, which ->
                    dialog.dismiss()
                    when (which) {
                        DialogInterface.BUTTON_POSITIVE -> {
                            if (!MapUtil.isGPSRunning(this@MainActivity)) {
                                ToastUtil.showLong("请打开GPS服务")
                                rejectGetLocation(407, "访问权限拒绝", "未打开 GPS 服务")
                                return@showSimpleDialog
                            }
                            AndPermission.with(this@MainActivity).runtime()
                                .permission(Permission.Group.LOCATION)
                                .rationale { context, data, executor ->
                                    rejectGetLocation(407, "访问权限拒绝", "未授予获取位置信息权限")
                                    ToastUtil.showShort("授权后才能使用")
                                }
                                .onDenied {
                                    rejectGetLocation(407, "访问权限拒绝", "未授予获取位置信息权限")
                                    ToastUtil.showShort("授权后才能使用")
                                }
                                .onGranted {
                                    obtainLocationTimer = Timer()
                                    obtainLocationTimer?.schedule(object : TimerTask() {
                                        override fun run() {
                                            if (!hasGetLocation) {
                                                rejectGetLocation(408, "获取地理位置信息超时", "获取地理位置超时")
                                                hasGetLocation = false
                                            }
                                        }

                                    }, OBTAIN_LOCATION_TIME_OUT)
                                    MyProgressDialog.showMessage(
                                        this@MainActivity,
                                        "获取位置信息中..."
                                    )
                                    IvcsApplication.startLocation(object :
                                        MapUtil.OnRefreshLocationListener {
                                        override fun onRefreshLocation(mapLocationBean: MapLocationBean?) {
                                            MyProgressDialog.dismissProgress()
                                            hasGetLocation = true
                                            val systemTraceBean = SystemTraceBean()
                                            systemTraceBean.businessType =
                                                SystemTraceType.GET_CUSTOMER_LOCATION
                                            systemTraceBean.message = "获取地理位置成功"
                                            val result = SystemTraceBean.Result()
                                            result.code = 200
                                            result.message = mapLocationBean?.address
                                            result.address = mapLocationBean
                                            systemTraceBean.result = result
                                            IvcsApplication.sendCustomMessage(
                                                systemTraceBean,
                                                object : IvcsCustomerCallback {
                                                    override fun onSuccess() {
                                                        IvcsApplication.ivcsCustomer!!.confirmRequestLocation(
                                                            MessageConfirmBean.Reply.OK,
                                                            null
                                                        )
                                                        addChatMessage(
                                                            MessageContent(
                                                                ChatRoleType.CUSTOMER,
                                                                SessionMessage(
                                                                    ChatMessageType.TEXT,
                                                                    mapLocationBean?.address
                                                                )
                                                            )
                                                        )
                                                    }

                                                    override fun onFailed(
                                                        code: Int,
                                                        error: String?
                                                    ) {
                                                    }

                                                })
                                            // 发送响应获取地理位置成功指令
                                            val getLocationResultBean = GetLocationResultBean()
                                            getLocationResultBean.address = mapLocationBean?.address
                                            val locationPosition =
                                                GetLocationResultBean.LocationPosition()
                                            locationPosition.lat = mapLocationBean?.lat!!
                                            locationPosition.lng = mapLocationBean?.lon!!
                                            // FIXME 设置 Q 和 R
                                            locationPosition.q
                                            locationPosition.r
                                            getLocationResultBean.position = locationPosition
                                            requestLocationSessionMessage.data.data =
                                                getLocationResultBean
                                            requestLocationSessionMessage.data.status =
                                                CommandStatus.DONE
                                            IvcsApplication.ivcsCustomer!!.sendPeerResponse(
                                                requestLocationSessionMessage.from,
                                                requestLocationSessionMessage.data, null
                                            )
                                        }

                                        override fun onFailure(result: String?) {
                                            MyProgressDialog.dismissProgress()
                                            hasGetLocation = true
                                            rejectGetLocation(409, "百度地图获取地理位置失败", "获取地理位置失败")
                                        }
                                    })
                                }.start()
                        }
                        DialogInterface.BUTTON_NEGATIVE -> {
                            rejectGetLocation(410, "用户拒绝授予位置信息", "获取地理位置失败")
                        }
                    }
                }
            }
        }

        override fun onVideoLabel(
            s: String, b: Boolean, videoWidth: Int,
            videoHeight: Int
        ) {
            roomFragment?.updateView(s, b, videoWidth, videoHeight)
        }

        override fun onDrop(s: String) {
            showToast(getString(R.string.service_stop_by_server))
            finish()
        }

        override fun onIMMessage(imMessage: SessionMessage<*>?) {
            if (imMessage?.type == ChatMessageType.TEXT && (TextUtils.isEmpty(imMessage.data?.toString()) ||
                        imMessage.data.toString().contains("silence-msg") ||
                        imMessage.data.toString().contains("OnTaskFailed") ||
                        imMessage.data.toString().contains("Timeout to make rpc"))
            ) {
                return
            }
            val messageContent = MessageContent(
                if (imMessage?.fromUser?.id?.toString() == IvcsApplication.customerTokenBody?.data?.id) {
                    ChatRoleType.CUSTOMER
                } else {
                    ChatRoleType.AGENT
                }, imMessage
            )
            addChatMessage(messageContent)
            // TODO 这里的判断不严谨，等新的聊天消息方案确定后，根据用户来更新聊天消息
            if (isRobot) {
                roomFragment?.notifyRobotMessage(messageContent)
            }
        }

        override fun onCmdView(cmdViewSessionMessage: SessionMessage<Command<LinkInfo>>) {
            addChatMessage(MessageContent(ChatRoleType.AGENT, cmdViewSessionMessage))
            val type = cmdViewSessionMessage.data.data.type
            val url = cmdViewSessionMessage.data.data.url
            runOnUiThread {
                val message = when (type) {
                    LinkType.LINK_PAGE -> {
                        "坐席推送链接"
                    }
                    LinkType.LINK_PAPER -> {
                        "坐席邀请您查看合同文件"
                    }
                    LinkType.LINK_VIDEO -> {
                        "坐席推送视频"
                    }
                    else -> {
                        "坐席推送链接"
                    }
                }
                AlertDialog.Builder(this@MainActivity)
                    .setTitle(getString(R.string.dialog_title_tips))
                    .setMessage(message)
                    .setPositiveButton(getString(R.string.confirm)) { dialog: DialogInterface?, which: Int ->
                        when (type) {
                            LinkType.LINK_PAGE, LinkType.LINK_VIDEO -> {
                                showFragment(
                                    WebViewFragment.getInstance(
                                        url,
                                        object : BaseCallback {
                                            override fun onClose() {
                                                agreeAgent()
                                            }
                                        })
                                )
                            }
                            LinkType.LINK_PAPER -> {
                                showFragment(
                                    PdfviewFragment.getInstance(
                                        url,
                                        object : BaseCallback {
                                            override fun onClose() {
                                                agreeAgent()
                                            }
                                        })
                                )
                            }
                            else -> {
                                val intent = Intent(Intent.ACTION_VIEW)
                                intent.data = Uri.parse(url)
                                startActivity(intent)
                                agreeAgent()
                            }
                        }
                    }
                    // 改成不允许取消
                    // .setNegativeButton(getString(R.string.cancel)) { dialog: DialogInterface?, which: Int -> rejectAgent() }
                    .create().show()
            }
        }

        override fun onError(i: Int) {
            showToast(i.toString())
        }

        override fun onFormData(
            formSessionMessage: SessionMessage<Command<FormBriefBean>>?,
            formUrl: String?,
            cancel: Boolean
        ) {
            val formImMessage = SessionMessage<Command<Any>>(ChatMessageType.COMMAND)
            formImMessage.fromUser = formSessionMessage?.fromUser
            val formBriefBean = formSessionMessage?.data?.data
            runOnUiThread {
                if (cancel) {
                    formImMessage.data = Command(CcsMessage.CCS_SEND_FORM, "取消表单")
                    addChatMessage(MessageContent(ChatRoleType.AGENT, formImMessage))
                    if (hasShowForm) {
                        hasShowForm = false
                        // 坐席主动终止的要主动改变状态
                        hasSubmitForm = true
                        removeFragment()
                    }
                } else {
                    formImMessage.data = Command(CcsMessage.CCS_SEND_FORM, "推送表单")
                    addChatMessage(MessageContent(ChatRoleType.AGENT, formImMessage))
                    formBriefBean?.let {
                        hasShowForm = true
                        hasSubmitForm = false
                        val javascriptInterfaces = HashMap<String, MyJavascriptInterface>()
                        javascriptInterfaces["ivcsCustomer"] = object : MyJavascriptInterface() {
                            @SuppressLint("JavascriptInterface")
                            @JavascriptInterface
                            fun updateFormSubmit(jsonString: String?) {
                                hasShowForm = false
                                hasSubmitForm = true
                                val jsonObject = JSONObject(jsonString)
                                if (jsonObject?.optInt("status") == 200) {
                                    GlobalScope.launch(Dispatchers.Main) {
                                        // 待web的弹窗效果展示完毕再关闭界面
                                        delay(2000)
                                        val messageConfirmBean = MessageConfirmBean<FormBriefBean>()
                                        messageConfirmBean.answer =
                                            MessageConfirmBean.Reply.OK.value()
                                        messageConfirmBean.type = CcsMessage.CCS_SEND_FORM
                                        messageConfirmBean.data = formBriefBean
                                        IvcsApplication.sendMessageConfirmation(
                                            messageConfirmBean,
                                            null
                                        )
                                        // 发送表单填写完成消息
                                        formSessionMessage.data.status = CommandStatus.DONE
                                        IvcsApplication.ivcsCustomer!!.sendPeerResponse(
                                            null,
                                            formSessionMessage.data,
                                            null
                                        )
                                        removeFragment()
                                        ToastUtil.showTopToast("提交表单成功！", Toast.LENGTH_LONG)
                                        addChatMessage(
                                            MessageContent(
                                                ChatRoleType.CUSTOMER, SessionMessage(
                                                    ChatMessageType.COMMAND,
                                                    Command(
                                                        CcsMessage.CCS_SEND_FORM,
                                                        "提交表单 <${formBriefBean.formName}> 成功"
                                                    )
                                                )
                                            )
                                        )
                                    }
                                } else {
                                    GlobalScope.launch(Dispatchers.Main) {
                                        removeFragment()
                                        ToastUtil.showTopToast("提交表单失败！", Toast.LENGTH_LONG)
                                        addChatMessage(
                                            MessageContent(
                                                ChatRoleType.CUSTOMER, SessionMessage(
                                                    ChatMessageType.COMMAND,
                                                    Command(
                                                        CcsMessage.CCS_SEND_FORM,
                                                        "提交表单 <${formBriefBean.formName}> 失败"
                                                    )
                                                )
                                            )
                                        )
                                    }
                                }
                            }
                        }
                        showFragment(
                            WebViewFragment.getInstance(
                                formUrl,
                                javascriptInterfaces, object : BaseCallback {
                                    override fun onClose() {
                                        if (!hasSubmitForm && supportFragmentManager.fragments.last() !is WebViewFragment) {
                                            hasShowForm = false
                                            formSessionMessage.data.status = CommandStatus.FAILED
                                            IvcsApplication.ivcsCustomer!!.sendPeerResponse(
                                                null,
                                                formSessionMessage.data,
                                                null
                                            )
                                            addChatMessage(
                                                MessageContent(
                                                    ChatRoleType.CUSTOMER, SessionMessage(
                                                        ChatMessageType.COMMAND,
                                                        Command(
                                                            CcsMessage.CCS_SEND_FORM,
                                                            "取消填写表单 <${formBriefBean.formName}>"
                                                        )
                                                    )
                                                )
                                            )
                                        }
                                    }
                                })
                        )
                    }
                }
            }
        }

        override fun onUserJoined(userInfo: SessionMessage.OriginUserBean) {
            joinedUsers.add(userInfo)
            isRobot = false
            if (formId > 0) {
                // 当访客提交了资料信息，这里需要通知一下系统
                IvcsApplication.ivcsCustomer!!.updateForm(formId, null)
            }
            agentNumber++
            addChatMessage(
                MessageContent(
                    ChatRoleType.SYSTEM,
                    SessionMessage(ChatMessageType.TEXT, "坐席${userInfo.name}加入会话")
                )
            )
            // 其他用户加入到会话中，一般是 座席端‘
            showToast(userInfo.name + getString(R.string.join_room))
            userInfo.profile?.let {
                if (it.isRobot) {
                    isRobot = true
                    roomFragment?.showSubTitle(true)
                }
            }
        }

        override fun onUserQuit(userInfo: SessionMessage.OriginUserBean) {
            joinedUsers.forEach {
                if (it.id == userInfo.id) {
                    joinedUsers.remove(it)
                    return@forEach
                }
            }
            showToast(userInfo.name + getString(R.string.exit_room))
            agentNumber--
            if (isTransfer) {
                isTransfer = false
                return
            }
            runOnUiThread {
                addChatMessage(
                    MessageContent(
                        ChatRoleType.SYSTEM,
                        SessionMessage(ChatMessageType.TEXT, "坐席${userInfo.name}离开会话")
                    )
                )
                if (userInfo.profile?.isRobot == true) {
                    roomFragment?.showSubTitle(false)
                }
                roomFragment?.try2Quit(userInfo.videoLabel)
            }
        }

        override fun onReadyTalk() {
            // 会话已经接通，访客端可以看到视频，和发送 readyTalk 消息不一样
            runOnUiThread {
                if (roomFragment == null) {
                    showToast(getString(R.string.service_connect_success))
                    showRoom()
                }
            }
        }

        override fun onHandSignature(handSignatureSessionMessage: SessionMessage<Command<Any>>) {
            runOnUiThread {
                val handSignatureImMessage = SessionMessage<Command<Any>>(ChatMessageType.COMMAND)
                handSignatureImMessage.fromUser = handSignatureSessionMessage.fromUser
                handSignatureImMessage.data = Command(CcsMessage.CCS_HANDWRITING , "邀请签名")
                addChatMessage(MessageContent(ChatRoleType.AGENT , handSignatureImMessage))
                AlertDialog.Builder(this@MainActivity)
                    .setTitle(getString(R.string.dialog_title_tips))
                    .setMessage("坐席给您发送了签名邀请")
                    .setPositiveButton(getString(R.string.confirm)) { dialog: DialogInterface?, which: Int ->
                        handSignatureSessionMessage.data.status = CommandStatus.ACCEPTED
                        IvcsApplication.ivcsCustomer!!.sendPeerResponse(null,
                            handSignatureSessionMessage.data,
                            object : IvcsCustomerCallback {
                                override fun onSuccess() {
                                    runOnUiThread {
                                        addChatMessage(MessageContent(ChatRoleType.CUSTOMER, SessionMessage(ChatMessageType.COMMAND ,
                                            Command(CcsMessage.CCS_HANDWRITING , "同意签名"))))
                                        showFragment(
                                            SignatureFragment.getInstance(
                                                handSignatureSessionMessage.data,
                                                object : BaseCallback {
                                                    override fun onClose() {
                                                        agreeAgent()
                                                    }
                                                })
                                        )
                                    }
                                }

                                override fun onFailed(code: Int, error: String?) {
                                    showToast(error)
                                }
                            })
                    }
                    // 改成不允许取消
                    // .setNegativeButton(getString(R.string.cancel)) { dialog: DialogInterface?, which: Int -> rejectAgent() }
                    .create().show()
            }
        }

        override fun onGuideBox(guideBoxSessionMessage: SessionMessage<Command<Any>>) {
            runOnUiThread {
                val guideBoxImMessage = SessionMessage<Command<Any>>(ChatMessageType.COMMAND)
                guideBoxImMessage.fromUser = guideBoxSessionMessage.fromUser
                guideBoxImMessage.data = Command(CcsMessage.PHOTO_GUIDEBOX, "推送引导框")
                addChatMessage(MessageContent(ChatRoleType.AGENT, guideBoxImMessage))
                roomFragment?.showGuideBox()
            }
        }

        override fun onScreenSnapshot(snapshotMessage: SessionMessage<Command<Any>>) {
            runOnUiThread {
                val snapshotImMessage = SessionMessage<Command<Any>>(ChatMessageType.COMMAND)
                snapshotImMessage.fromUser = snapshotMessage.fromUser
                snapshotImMessage.data = Command(CcsMessage.CCS_SNAPSHOT, "请求截图")
                addChatMessage(MessageContent(ChatRoleType.AGENT, snapshotImMessage))
                AlertDialog.Builder(this@MainActivity)
                    .setTitle(getString(R.string.dialog_title_tips))
                    .setMessage("坐席请求截图您的摄像头画面")
                    .setPositiveButton(getString(R.string.confirm)) { dialog: DialogInterface?, which: Int ->
                        addChatMessage(
                            MessageContent(
                                ChatRoleType.CUSTOMER, SessionMessage(
                                    ChatMessageType.COMMAND,
                                    Command(CcsMessage.CCS_SNAPSHOT, "同意截图")
                                )
                            )
                        )
                        IvcsApplication.ivcsCustomer?.snapshot(
                            null, snapshotMessage.data.cmdId,
                            BaseManager.LOCAL_RENDER,
                            object : ServerCallback<LinkInfo>() {
                                override fun onSuccess(t: LinkInfo?) {
                                    super.onSuccess(t)
                                    val snapshotCommand = Command<LinkInfo>()
                                    snapshotCommand.data = t
                                    addChatMessage(
                                        MessageContent(
                                            ChatRoleType.CUSTOMER,
                                            SessionMessage(ChatMessageType.PICTURE, snapshotCommand)
                                        )
                                    )
                                }
                            })
                    }
                    // 改成不允许取消
                    // .setNegativeButton(getString(R.string.cancel)) { dialog: DialogInterface?, which: Int -> rejectAgent() }
                    .create().show()
            }
        }

        override fun onRemoteControl(remoteControlSessionMessage: SessionMessage<Command<Any>>) {
            var manager: MediaProjectionManager? = null
            manager =
                application.getSystemService(MEDIA_PROJECTION_SERVICE) as MediaProjectionManager
            startActivityForResult(manager.createScreenCaptureIntent(), REQUEST_SHARE_CODE)
        }

        override fun onMakeChoice(makeChoiceSessionMessage: SessionMessage<Command<MutableList<String>>> , cancel:Boolean) {
            runOnUiThread {
                if (cancel){
                    if (supportFragmentManager.fragments.last() is MakeChoiceFragment){
                        removeFragment()
                    }
                }else{
                    showFragment(MakeChoiceFragment(makeChoiceSessionMessage))
                }
            }
        }

        override fun onMarkScreen(x: Int, y: Int) {
            LogUtil.d("markScreen:$x , $y")
            runOnUiThread {
                overlayPermissionUtil =
                    OverlayPermissionUtil(object :
                        OverlayPermissionUtil.OnWindowPermissionListener {
                        override fun onSuccess() {
                            val uuid = UUID.randomUUID()
                            val id = uuid.toString()
                            runOnUiThread { tipsBinder!!.callShowOver(id, x, y) }
                            val timer = Timer()
                            timer.schedule(object : TimerTask() {
                                override fun run() {
                                    runOnUiThread { tipsBinder!!.callHideOver(id) }
                                }
                            }, 3000)
                        }

                        override fun onFailure() {
                        }

                    })
                overlayPermissionUtil!!.checkPermission(this@MainActivity)
            }
        }

        override fun onCustomMessage(customMessage: SessionMessage<Any>) {
            LogUtil.d("customMessage ${GsonUtil.object2String(customMessage)}")
            GsonUtil.toJSONObject(customMessage.data)
                ?.let {
                    val businessType = it.optString("businessType", null)
                    if (!TextUtils.isEmpty(businessType)) {
                        var messageContent: MessageContent? = null
                        when (businessType) {
                            SystemTraceType.START_FACE_COMPARE,
                            SystemTraceType.START_SCREEN, SystemTraceType.STOP_SCREEN,
                            SystemTraceType.START_MARK, SystemTraceType.STOP_MARK,
                            SystemTraceType.GUIDE_BOX, SystemTraceType.HAND_SIGN,
                            SystemTraceType.START_REMOTE_ASSISTANCE, SystemTraceType.STOP_REMOTE_ASSISTANCE,
                            SystemTraceType.START_RECORD_SCREEN, SystemTraceType.STOP_RECORD_SCREEN,
                            SystemTraceType.SEND_PDF
                            -> {
                                messageContent =
                                    ChatMessageUtil.addText(
                                        it.optString("message", ""),
                                        "",
                                        ChatRoleType.AGENT
                                    )
                            }
                            SystemTraceType.FACE_COMPARE_RESULT -> {
                                GsonUtil.toObject(
                                    it.optString("result", ""),
                                    SystemTraceBean.Result::class.java
                                )?.let { result ->
                                    var text: String? = null
                                    text = if (result.code == 200) {
                                        "人脸识别成功"
                                    } else {
                                        "人脸识别失败"
                                    }
                                    messageContent =
                                        ChatMessageUtil.addText(text, "", ChatRoleType.AGENT)
                                }
                            }
                            SystemTraceType.SEND_PAGE_LINK -> {
                                GsonUtil.toObject(
                                    it.optString("info", ""),
                                    SystemTraceBean.Info::class.java
                                )?.let { info ->
                                    messageContent = MessageContent(
                                        ChatRoleType.AGENT,
                                        SessionMessage(ChatMessageType.TEXT, "推送链接地址 ${info.url}")
                                    )
                                }
                            }
                            SystemTraceType.SEND_VIDEO_LINK -> {
                                GsonUtil.toObject(
                                    it.optString("info", ""),
                                    SystemTraceBean.Info::class.java
                                )?.let { info ->
                                    messageContent = MessageContent(
                                        ChatRoleType.AGENT,
                                        SessionMessage(ChatMessageType.TEXT, "推送视频文件 ${info.url}")
                                    )
                                }
                            }
                            SystemTraceType.AGENT_COLLECT_IMAGE -> {
                                roomFragment?.uploadCollectImage(it.optInt("info"))
                            }
                            SystemTraceType.AGENT_COLLECT_INFORMATION -> {
                                try {
                                    val jsonObject: JSONObject = it.getJSONObject("result")
                                    GsonUtil.toObject(
                                        jsonObject.toString(),
                                        CollectedCustomerInfo::class.java
                                    )?.let {
                                        runOnUiThread {
                                            val dialogCollectCustomerInfoBinding =
                                                DialogCollectCustomerInfoBinding.inflate(
                                                    layoutInflater
                                                )
                                            dialogCollectCustomerInfoBinding.etCustomerName.text =
                                                it.name
                                            dialogCollectCustomerInfoBinding.etPhoneNumber.text =
                                                it.mobile
                                            dialogCollectCustomerInfoBinding.tvCategory.text =
                                                it.productCategory
                                            dialogCollectCustomerInfoBinding.etIdCardNumber.text =
                                                it.id
                                            dialogCollectCustomerInfoBinding.etCompanyName.text =
                                                it.company
                                            dialogCollectCustomerInfoBinding.etAddress.text =
                                                it.address
                                            AlertDialogUtil.show(
                                                dialogCollectCustomerInfoBinding.root
                                            ) { _ ->
                                                IvcsApplication.confirmCollect(
                                                    it,
                                                    object :
                                                        ServerCallback<SubmitIDAndBankInfoResultBean>() {

                                                        override fun onSuccess(t: SubmitIDAndBankInfoResultBean?) {
                                                            t?.data?.id?.let {
                                                                submitUserInfo(it)
                                                            }
                                                        }

                                                        override fun failedResponse(result: String?) {
                                                        }

                                                    })

                                                AlertDialogUtil.dismiss()
                                            }
                                        }
                                    }

                                } catch (e: JSONException) {
                                    e.printStackTrace()
                                }
                            }
                            else -> {

                            }
                        }
                        // addChatMessage(messageContent)
                    }
                }
        }

        override fun onTransferring(transferringSessionMessage: SessionMessage<HoldOnData>) {
            isTransfer = true
            runOnUiThread {
                val transferringImMessage = SessionMessage<Command<Any>>(ChatMessageType.COMMAND)
                transferringImMessage.fromUser = transferringSessionMessage.fromUser
                transferringImMessage.data = Command(CcsMessage.CCS_HOLD_ON ,
                    "发起了场景转接到 <${transferringSessionMessage.data.transferInfo.bizSceneName}>")
                addChatMessage(MessageContent(ChatRoleType.AGENT , transferringImMessage))
                roomFragment?.showSubTitle(false)
                roomFragment?.showHangOn()
            }
        }

        override fun onInvitationProgress(invitationProgressBean: InvitationProgressBean) {
            runOnUiThread {
                when (invitationProgressBean?.status) {
                    InvitationProgressType.NOT_FOUND -> {
                        ToastUtil.showTopToast(getString(R.string.not_found_services))
                        finish()
                    }
                    InvitationProgressType.OFF_TIME -> {
                        ToastUtil.showTopToast("当前为非工作日，请在工作日内呼叫", Toast.LENGTH_LONG)
                        finish()
                    }
                    InvitationProgressType.WAITING -> {
                        when(invitationProgressBean?.waitingReasonMessage){
                            "No available agent" ->{
                                // 不需要提示用户
                            }
                            else->{
                                roomFragment?.showWaiting(invitationProgressBean)
                            }
                        }
                    }
                    InvitationProgressType.CONNECTING -> {
                        roomFragment?.showWaiting(invitationProgressBean)
                    }
                    InvitationProgressType.ACCEPTED -> {

                    }
                }
            }
        }

        override fun onWorkFlowProgress(workFlowProgressBeanSessionMessage: SessionMessage<WorkFlowProgressBean>) {

        }

        private fun agreeAgent() {
            IvcsApplication.replyAiAgent(ReplyAiAgentBean(MessageConfirmBean.Reply.OK))
        }

        private fun rejectAgent() {
            IvcsApplication.replyAiAgent(ReplyAiAgentBean(MessageConfirmBean.Reply.REJECT))
        }

    }

    /**
     * 处理提交用户信息后返回的表单 id
     * @param userInfoString 的格式为 {"code":200,"data":{"id":90,"message":"新增成功！"}}
     */
    fun submitUserInfo(formId: Int) {
        this.formId = formId
        IvcsApplication.ivcsCustomer?.updateForm(formId, null)
        val systemTraceBean = SystemTraceBean()
        systemTraceBean.businessType = SystemTraceType.SEND_FORM
        systemTraceBean.message = "提交个人信息成功"
        systemTraceBean.result = SystemTraceBean.Result()
        systemTraceBean.result!!.code = 200
        systemTraceBean.result!!.formId = formId
        systemTraceBean.result!!.message = "确认提交个人资料"
        IvcsApplication.sendCustomMessage(systemTraceBean, object : IvcsCustomerCallback {
            override fun onSuccess() {

            }

            override fun onFailed(code: Int, error: String?) {
            }
        })
    }

    fun addChatMessage(content: MessageContent?) {
        content?.let {
            if (messageContents.size <= 0 || (it.createTime - messageContents[messageContents.size - 1].createTime > 60000)) {
                // 超过 1min 没有消息，则添加上时间
                messageContents.add(
                    MessageContent(
                        ChatRoleType.TIME, SessionMessage(
                            ChatMessageType.TEXT,
                            SimpleDateFormat(
                                "yyyy/MM/dd ${
                                    if (Calendar.getInstance()
                                            .get(Calendar.HOUR_OF_DAY) >= 12
                                    ) "下午" else "上午"
                                } HH:mm:ss"
                            ).format(Date(it.createTime))
                        )
                    )
                )
            }
            messageContents.add(it)
            mChatRoomFragment?.notifyListView()
        }
    }

    private fun hangup() {
        AlertDialogUtil.showSimpleDialog(
            this@MainActivity, "是否结束会话？"
        ) { dialog, which ->
            dialog.dismiss()
            if (which == AlertDialog.BUTTON_POSITIVE) {
                finish()
            }
        }
    }

    override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
        val fragmentsCount = supportFragmentManager.fragments?.size
        var fragment: Fragment? = null
        if (fragmentsCount != null) {
            if (fragmentsCount > 0) {
                fragment = supportFragmentManager.fragments[fragmentsCount - 1]
                if (fragment is BaseFragment) {
                    fragment.onKeyDown(keyCode, event)
                }
            }
        }
        if (keyCode == KeyEvent.KEYCODE_BACK && fragment is RoomFragment) {
            hangup()
            return true
        }
        return super.onKeyDown(keyCode, event)
    }

    private fun getBusinessScenario() {
        IvcsApplication.ivcsCustomer?.getBusinessScenario(
            "enabled",
            object : ServerCallback<BusinessScenariosBean>() {

                override fun onSuccess(t: BusinessScenariosBean?) {
                    super.onSuccess(t)
                    t?.let {
                        businessScenarioList.clear()
                        businessScenarioList.addAll(it.scenList)
                    }
                }

                override fun failedResponse(result: String?) {
                }

            })
    }

}